﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Collections;

namespace TMall.Framework.Caching
{
    /// <summary>
    /// 同一个HttpContext实例的缓存提供器,一次请求流程内缓存有效
    /// </summary>
    public class PerRequestCacheManager : ICacheProvider
    {
        /// <summary>
        /// Http请求上下文基类
        /// </summary>
        private readonly HttpContextBase _context;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="context">Context</param>
        public PerRequestCacheManager(HttpContextBase context)
        {
            this._context = context;
        }

        /// <summary>
        /// 获取使用HttpContext内置一次性缓存
        /// </summary>
        /// <returns></returns>
        protected IDictionary GetItems()
        {
            if (_context != null)
                return _context.Items;

            return null;
        }

        /// <summary>
        /// 向缓存中添加一个对象。
        /// </summary>
        /// <param name="key">缓存的键值，该值通常是使用缓存机制的方法的名称。</param>
        /// <param name="valKey">缓存值的键值，该值通常是由使用缓存机制的方法的参数值所产生。</param>
        /// <param name="value">需要缓存的对象。</param>
        /// <param name="cacheTime">需要过期时间。</param> 
        public void Add(string key, string valKey, object value, int cacheTime = int.MaxValue)
        {
            var items = GetItems();
            if (items == null)
                return;

            if (value != null)
            {
                Dictionary<string, object> dict = null;
                if (items.Contains(key))
                {
                    dict = (Dictionary<string, object>)items[key];
                    dict[valKey] = value;
                }
                else
                {
                    dict = new Dictionary<string, object>();
                    dict.Add(valKey, value);
                }

                items.Add(key, dict);
            }
        }

        /// <summary>
        /// 向缓存中添加一个对象。
        /// </summary>
        /// <param name="key">缓存的键值，该值通常是使用缓存机制的方法的名称。</param>
        /// <param name="valKey">缓存值的键值，该值通常是由使用缓存机制的方法的参数值所产生。</param>
        /// <param name="value">需要缓存的对象。</param>
        public void Add(string key, string valKey, object value)
        {
            var items = GetItems();
            if (items == null)
                return;

            if (value != null)
            {
                Dictionary<string, object> dict = null;
                if (items.Contains(key))
                {
                    dict = (Dictionary<string, object>)items[key];
                    dict[valKey] = value;
                }
                else
                {
                    dict = new Dictionary<string, object>();
                    dict.Add(valKey, value);
                }

                items.Add(key, dict);
            }
        }

        /// <summary>
        /// 向缓存中添加一个对象。
        /// </summary>
        /// <param name="key">缓存的键值，该值通常是使用缓存机制的方法的名称。</param>
        /// <param name="valKey">缓存值的键值，该值通常是由使用缓存机制的方法的参数值所产生。</param>
        /// <param name="value">需要缓存的对象。</param>
        /// <param name="value">活动过期时间。</param>
        public void Add(string key, string valKey, object value, TimeSpan slidingExpiration)
        {
            Add(key, valKey, value);
        }

        /// <summary>
        /// 向缓存中添加一个对象。
        /// </summary>
        /// <param name="key">缓存的键值，该值通常是使用缓存机制的方法的名称。</param>
        /// <param name="valKey">缓存值的键值，该值通常是由使用缓存机制的方法的参数值所产生。</param>
        /// <param name="value">需要缓存的对象。</param>
        /// <param name="value">绝对过期时间。</param>
        public void Add(string key, string valKey, object value, DateTime absoluteExpiration)
        {
            Add(key, valKey, value);
        }

        /// <summary>
        /// 向缓存中更新一个对象。
        /// </summary>
        /// <param name="key">缓存的键值，该值通常是使用缓存机制的方法的名称。</param>
        /// <param name="valKey">缓存值的键值，该值通常是由使用缓存机制的方法的参数值所产生。</param>
        /// <param name="value">需要缓存的对象。</param>
        public void Put(string key, string valKey, object value)
        {
            Add(key, valKey, value);
        }

        /// <summary>
        /// 向缓存中更新一个对象。
        /// </summary>
        /// <param name="key">缓存的键值，该值通常是使用缓存机制的方法的名称。</param>
        /// <param name="valKey">缓存值的键值，该值通常是由使用缓存机制的方法的参数值所产生。</param>
        /// <param name="value">需要缓存的对象。</param>
        /// <param name="value">活动过期时间。</param>
        public void Put(string key, string valKey, object value, TimeSpan slidingExpiration)
        {
            Add(key, valKey, value);
        }

        /// <summary>
        /// 向缓存中更新一个对象。
        /// </summary>
        /// <param name="key">缓存的键值，该值通常是使用缓存机制的方法的名称。</param>
        /// <param name="valKey">缓存值的键值，该值通常是由使用缓存机制的方法的参数值所产生。</param>
        /// <param name="value">需要缓存的对象。</param>
        /// <param name="value">绝对过期时间。</param>
        public void Put(string key, string valKey, object value, DateTime absoluteExpiration)
        {
            Add(key, valKey, value);
        }

        /// <summary>
        /// 从缓存中读取对象。
        /// </summary>
        /// <param name="key">缓存的键值，该值通常是使用缓存机制的方法的名称。</param>
        /// <param name="valKey">缓存值的键值，该值通常是由使用缓存机制的方法的参数值所产生。</param>
        public T Get<T>(string key, string valKey)
        {
            var value = Get(key, valKey);
            return value == null ? default(T) : (T)value;
        }

        /// <summary>
        /// 从缓存中读取对象。
        /// </summary>
        /// <param name="key">缓存的键值，该值通常是使用缓存机制的方法的名称。</param>
        /// <param name="valKey">缓存值的键值，该值通常是由使用缓存机制的方法的参数值所产生。</param>
        public object Get(string key, string valKey)
        {
            var items = GetItems();
            if (items == null || !items.Contains(key))
                return null;

            Dictionary<string, object> dict = (Dictionary<string, object>)items[key];
            if (dict != null && dict.ContainsKey(valKey))
                return dict[valKey];
            else
                return null;
        }

        /// <summary>
        /// 从缓存中移除对象。
        /// </summary>
        /// <param name="key">缓存的键值，该值通常是使用缓存机制的方法的名称。</param>
        public void Remove(string key)
        {
            var items = GetItems();
            if (items == null)
                return;

            items.Remove(key);
        }

        /// <summary>
        /// 获取一个<see cref="Boolean"/>值，该值表示拥有指定键值的缓存是否存在。
        /// </summary>
        /// <param name="key">指定的键值。</param>
        /// <returns>如果缓存存在，则返回true，否则返回false。</returns>
        public bool Exists(string key)
        {
            var items = GetItems();
            if (items == null)
                return false;

            return (items[key] != null);
        }

        /// <summary>
        /// 获取一个<see cref="Boolean"/>值，该值表示拥有指定键值和缓存值键的缓存是否存在。
        /// </summary>
        /// <param name="key">指定的键值。</param>
        /// <param name="valKey">缓存值键。</param>
        /// <returns>如果缓存存在，则返回true，否则返回false。</returns>
        public bool Exists(string key, string valKey)
        {
            var items = GetItems();
            if (items == null)
                return false;

            Dictionary<string, object> dict = (Dictionary<string, object>)items[key];
            return dict != null && dict.ContainsKey(valKey);
        }

        /// <summary>
        /// 清空所有缓存
        /// </summary>
        public void FlushAll()
        {
            var items = GetItems();
            if (items == null)
                return;

            var enumerator = items.GetEnumerator();
            var keysToRemove = new List<String>();
            while (enumerator.MoveNext())
            {
                keysToRemove.Add(enumerator.Key.ToString());
            }

            foreach (string key in keysToRemove)
            {
                items.Remove(key);
            }
        }
    }
}
